﻿using System;
using System.Data;
using System.Data.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Ue.Framework.Collections;
using Ue.Framework;

namespace Ue.Qcdz.Repositories
{
    public class SqlServerDriver : Ue.Infrastructure.RepositoryFramework.Repository.IRepositoryDriver
    {
        #region 单例

        private static class SqlServerDriverHolder
        {
            public static SqlServerDriver sqlServerDriver = new SqlServerDriver();
        }

        public static SqlServerDriver Instance
        {
            get { return SqlServerDriverHolder.sqlServerDriver; }
        }

        #endregion

        private Database database;

        private SqlServerDriver()
        {
            this.database = DatabaseFactory.CreateDatabase();
        }

        public IDataReader ExecuteReader(IDbCommand command)
        {
            return this.database.ExecuteReader((DbCommand)command);
        }
        public IDataReader ExecuteReader(string sql, params IDataParameter[] parameters)
        {
            return this.ExecuteReader(this.BuildCommand(sql, parameters));
        }

        public int ExecuteNonQuery(IDbCommand command)
        {
            return this.database.ExecuteNonQuery((DbCommand)command);
        }
        public int ExecuteNonQuery(string sql, params IDataParameter[] parameters)
        {
            return this.ExecuteNonQuery(this.BuildCommand(sql, parameters));
        }

        public TReturn ExecuteScalar<TReturn>(IDbCommand command)
        {
            return this.database.ExecuteScalar((DbCommand)command).As<TReturn>();
        }
        public TReturn ExecuteScalar<TReturn>(string sql, params IDataParameter[] parameters)
        {
            return this.ExecuteScalar<TReturn>(this.BuildCommand(sql, parameters));
        }

        public IDbCommand BuildCommand(string sql)
        {
            IDbCommand command = this.database.DbProviderFactory.CreateCommand();

            command.CommandText = sql;

            command.CommandType = CommandType.Text;

            return command;
        }
        public IDbCommand BuildCommand(string sql, params IDataParameter[] parameters)
        {
            IDbCommand command = this.BuildCommand(sql);

            parameters.Foreach(item => 
            {
                //((ICloneable)item).Clone()执行一个深copy，不然会出现 当在一段程序中两次调command并且两个command有相同的参数时会报 SqlParameterCollection 已经包含xx个参数的错误。
                command.Parameters.Add(((ICloneable)item).Clone()); 
            });

            return command;
        }

        public IDataParameter BuildParameter()
        {
            return this.database.DbProviderFactory.CreateParameter();
        }
        public IDataParameter BuildParameter(string name, object value)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("parameterName参数不能为空。");
            }

            IDataParameter parameter = this.BuildParameter();

            parameter.ParameterName = this.BuildParameterName(name);

            if (value == null)
            {
                parameter.Value = DBNull.Value;
            }
            else
            {
                Type valueType = value.GetType();

                if (valueType.IsEnum)
                {
                    value = (int)value;
                }

                parameter.Value = value;
            }

            return parameter;
        }

        public string BuildParameterName(string name)
        {
            return this.database.BuildParameterName(name);
        }
    }
}
